package com.fullstack.app.pages.core

import cats.effect.IO
import cats.effect.IO.asyncForIO
import com.fullstack.app.App
import com.fullstack.app.pages.Page
import com.fullstack.app.pages.common.Constants
import org.scalajs.dom.{document, window}
import tyrian.{Cmd, Nav}
import tyrian.cmds.Logger
import tyrian.http.{HttpError, Method, Response}

import scala.scalajs.js.Date

final case class Session(userId: Option[String] = None, token: Option[String] = None) {
  
  import Session.*

  def initCmd: Cmd[IO, App.Msg] =
    val maybeCookie =
      for
        userId <- Commands.getCookie(Constants.cookies.userId)
        userName <- Commands.getCookie(Constants.cookies.userName)
        userPhone <- Commands.getCookie(Constants.cookies.userPhone)
        userPortraitUrl <- Commands.getCookie(Constants.cookies.userPortraitUrl)
        token <- Commands.getCookie(Constants.cookies.token)
      yield Cmd.Emit(SetToken(userId, userName, userPhone, userPortraitUrl, token))

    maybeCookie.getOrElse(Cmd.None)

  
  def update(msg: App.Msg): (Session, Cmd[IO, App.Msg])  =
    msg match
      case SetToken(userId, userName, userPhone, userPortraitUrl, token, isNewUser) =>
        val cookieCmd = Commands.setAllSessionCookie(userId, userName, userPhone, userPortraitUrl, token, true)
        val routeCmd =
          if isNewUser then
//            Cmd.Emit(Router.ChangeLocation.apply(Page.urls.home))
            Nav.pushUrl(Page.urls.home)
          else
            Nav.pushUrl(Page.urls.home)
        (
          this.copy(userId = Some(userId), token = Some(token)),
          cookieCmd |+| routeCmd
        )
      case Logout =>
        val flag = window.confirm("是否登出？")
        if flag then
          (
            this.copy(token = None),
            Commands.clearAllSessionCookie() |+| Nav.loadUrl(Page.urls.home) //Cmd.Emit(Router.ChangeLocation.apply(Page.urls.home))
          )
        else
          (this, Cmd.None)
        
      case LogoutError =>
        (this, Cmd.None)



}


object Session {
  trait SessionMsg extends App.Msg
  
  

  case class SetToken(userId: String, userName: String, userPhone: String, userPortraitUrl: String, token: String, isNewUser: Boolean = false) extends SessionMsg

  case object Logout extends SessionMsg
  case object LogoutSuccess extends SessionMsg
  case object LogoutError extends SessionMsg

  def isActive() =
    Commands.getCookie(Constants.cookies.token).nonEmpty

  def getUserToke() =
    Commands.getCookie(Constants.cookies.token)

  def getUserId() =
    Commands.getCookie(Constants.cookies.userId)

  def getUserPhone() =
    Commands.getCookie(Constants.cookies.userPhone)

  object Endpoints {

//    val logout = new Endpoint[Msg]{
//      override val location: String = Constants.endpoints.logout
//      override val method: Method = Method.Post
//      override val onResponse: Response => Msg = _ => LogoutSuccess
//      override val onError: HttpError => Msg = _ => LogoutError
//    }

  }

  object Commands {

    def setSessionCookie(name: String, value: String, isFresh: Boolean): Cmd[IO, SessionMsg] =
      Cmd.SideEffect {
        if getCookie(name).isEmpty || isFresh then
          document.cookie =
            s"$name=$value;expires=${new Date(Date.now() + Constants.cookies.duration)};path=/"
      }

    def setAllSessionCookie(userId: String, userName: String, userPhone: String, userPortraitUrl: String, token: String,  isFresh: Boolean): Cmd[IO, SessionMsg] =
      setSessionCookie(Constants.cookies.userId, userId, isFresh) |+|
        setSessionCookie(Constants.cookies.userName, userName, isFresh ) |+|
        setSessionCookie(Constants.cookies.userPhone, userPhone, isFresh) |+|
        setSessionCookie(Constants.cookies.userPortraitUrl, userPortraitUrl, isFresh) |+|
        setSessionCookie(Constants.cookies.token, token, isFresh)

    def clearSessionCookie(name: String): Cmd[IO, SessionMsg] =
      Cmd.SideEffect {
        document.cookie = s"$name=;expires=${new Date(0)};path=/"
      }

    def clearAllSessionCookie(): Cmd[IO, SessionMsg] =
      clearSessionCookie(Constants.cookies.userId) |+|
        clearSessionCookie(Constants.cookies.userName) |+|
        clearSessionCookie(Constants.cookies.userPhone) |+|
        clearSessionCookie(Constants.cookies.userPortraitUrl) |+|
        clearSessionCookie(Constants.cookies.token)

    def getCookie(name: String): Option[String] =
      document.cookie.split(";")
        .map(_.trim)
        .find(_.startsWith(s"$name="))
        .map(_.split("="))
        .map(
          arr => 
            if arr.length > 1 then
              arr(1)
            else
              ""
        )


//    def logout: Cmd[IO, Msg] =
//      Endpoints.logout.callAuth()


  }


}